#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
进程监控模块
负责Windows进程检测、启动和停止核心逻辑
"""

import psutil
import subprocess
import time
import threading
from logger import Logger


class ProcessMonitor:
    """进程监控器类"""

    def __init__(self, logger: Logger):
        """
        初始化进程监控器
        
        Args:
            logger (Logger): 日志管理器实例
        """
        self.logger = logger
        self.processes = []
        self.monitor_threads = []
        self.running = False

    def add_process(self, process_config):
        """
        添加要监控的进程
        
        Args:
            process_config (dict): 进程配置信息
        """
        process_info = {
            "config": process_config,
            "status": "未知",
            "last_start_time": None,
            "restart_count": 0,
            "monitoring": False
        }
        self.processes.append(process_info)

    def remove_process(self, index):
        """
        删除监控的进程
        
        Args:
            index (int): 进程索引
        """
        if 0 <= index < len(self.processes):
            # 停止监控线程
            self.processes[index]["monitoring"] = False
            del self.processes[index]

    def start_monitoring(self):
        """启动所有进程监控"""
        self.running = True
        for i, process in enumerate(self.processes):
            if not process["monitoring"]:
                thread = threading.Thread(target=self._monitor_process, args=(i,), daemon=True)
                thread.start()
                self.monitor_threads.append(thread)
                process["monitoring"] = True

    def stop_monitoring(self):
        """停止所有进程监控"""
        self.running = False
        for process in self.processes:
            process["monitoring"] = False

    def _monitor_process(self, index):
        """
        监控单个进程(在线程中运行)
        
        Args:
            index (int): 进程索引
        """
        while self.running and self.processes[index]["monitoring"]:
            try:
                process_config = self.processes[index]["config"]
                process_name = process_config["name"]
                
                # 检查进程是否在运行
                is_running = self._is_process_running(process_name)
                
                if is_running:
                    self.processes[index]["status"] = "运行中"
                else:
                    self.processes[index]["status"] = "已停止"
                    # 尝试重启进程
                    self._restart_process(index)
                
                # 等待指定的检测间隔
                interval = process_config.get("check_interval", 5)
                time.sleep(interval)
                
            except Exception as e:
                self.logger.error(f"监控进程 {self.processes[index]['config']['name']} 时出错: {str(e)}")
                time.sleep(5)  # 出错时等待5秒再继续

    def _is_process_running(self, process_name):
        """
        检查进程是否在运行
        
        Args:
            process_name (str): 进程名称(.exe文件名)
            
        Returns:
            bool: 进程是否在运行
        """
        for proc in psutil.process_iter(['name']):
            try:
                if proc.info['name'] == process_name:
                    return True
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        return False

    def _restart_process(self, index):
        """
        重启进程
        
        Args:
            index (int): 进程索引
        """
        process_config = self.processes[index]["config"]
        process_name = process_config["name"]
        max_retries = process_config.get("max_retries", 3)
        retry_interval = process_config.get("retry_interval", 10)
        
        self.processes[index]["restart_count"] += 1
        retry_count = self.processes[index]["restart_count"]
        
        if retry_count <= max_retries:
            self.logger.info(f"尝试重启进程 {process_name} (第 {retry_count} 次)")
            
            try:
                # 获取启动参数
                executable = process_config["executable"]
                args = process_config.get("args", "")
                work_dir = process_config.get("work_dir", None)
                
                # 构建命令
                cmd = [executable]
                if args:
                    cmd.extend(args.split())
                
                # 启动进程
                subprocess.Popen(
                    cmd,
                    cwd=work_dir,
                    creationflags=subprocess.CREATE_NEW_CONSOLE
                )
                
                self.processes[index]["last_start_time"] = time.strftime('%Y-%m-%d %H:%M:%S')
                self.logger.info(f"进程 {process_name} 重启成功")
                
            except Exception as e:
                self.logger.error(f"重启进程 {process_name} 失败: {str(e)}")
        else:
            self.logger.error(f"进程 {process_name} 重启失败次数超过限制 ({max_retries} 次)")
            self.processes[index]["status"] = "异常"
            self.processes[index]["restart_count"] = 0  # 重置计数器

    def get_process_status(self, index):
        """
        获取进程状态
        
        Args:
            index (int): 进程索引
            
        Returns:
            dict: 进程状态信息
        """
        if 0 <= index < len(self.processes):
            return self.processes[index]
        return None

    def start_process(self, index):
        """
        手动启动进程
        
        Args:
            index (int): 进程索引
        """
        if 0 <= index < len(self.processes):
            process_config = self.processes[index]["config"]
            try:
                executable = process_config["executable"]
                args = process_config.get("args", "")
                work_dir = process_config.get("work_dir", None)
                
                cmd = [executable]
                if args:
                    cmd.extend(args.split())
                
                subprocess.Popen(
                    cmd,
                    cwd=work_dir,
                    creationflags=subprocess.CREATE_NEW_CONSOLE
                )
                
                self.processes[index]["last_start_time"] = time.strftime('%Y-%m-%d %H:%M:%S')
                self.processes[index]["status"] = "运行中"
                self.logger.info(f"手动启动进程 {process_config['name']} 成功")
                return True
            except Exception as e:
                self.logger.error(f"手动启动进程 {process_config['name']} 失败: {str(e)}")
                return False
        return False

    def stop_process(self, index):
        """
        手动停止进程
        
        Args:
            index (int): 进程索引
        """
        if 0 <= index < len(self.processes):
            process_name = self.processes[index]["config"]["name"]
            
            # 查找并终止进程
            for proc in psutil.process_iter(['pid', 'name']):
                try:
                    if proc.info['name'] == process_name:
                        proc.terminate()
                        proc.wait(timeout=3)  # 等待进程终止
                        self.processes[index]["status"] = "已停止"
                        self.logger.info(f"手动停止进程 {process_name} 成功")
                        return True
                except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.TimeoutExpired):
                    pass
            
            self.logger.warning(f"未找到运行中的进程 {process_name}")
            return False
        return False